﻿// Copyright (c) Microsoft Corporation.  All rights reserved.
// The following example shows a very quick way to get started with the ADO.NET Entity Framework.

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml.Linq;

using MyPeopleModel;
using System.Data.Objects;

namespace GettingStarted_CS
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // don't do anything during postback
            if (IsPostBack)
                return;

            try
            {
                // the short lived MyTravelPostEntities creates/destroys the connection
                // for the life of the using statement.
                using (MyTravelPostEntities entities = new MyTravelPostEntities())
                {
                    // the NoTracking option disables identity resolution and change
                    // tracking in the ObjectStateManager. For short lived context and query
                    // this method would be fastest.
                    // NOTE: after Beta 3, you will be able to just call .First() instead
                    // of Take(1).ToArray()[0]
                    entities.BlogPosts.MergeOption = MergeOption.NoTracking;
                    BlogPost post = (from bp in entities.BlogPosts.Include("Comments.Person")
                                     where bp.Comments.Count() > 0
                                     select bp).Take(1).ToArray()[0];

                    // put the blog entry in the text.
                    textBlogEntry.Text = post.BlogEntry;

                    // update all these items first
                    UpdateComments(post);

                    // the entities support binary serialization, including the graphs
                    // but just as a note, if the NoTracking option is set, the you 
                    // may get circle references when reattaching. Since we spanned
                    // in all the commments and the people we are bound to 
                    // run into duplicate people when we reattach
                    // for now, we can just clear the comments and be good, since
                    // there no change tracking we aren't really delete, just removing
                    // from the list.
                    // or you can use a tracking query. - performance is just your issue
                    // and depth.
                    post.Comments.Clear();
                    ViewState["BlogPost"] = post;
                }
            }   
            catch (Exception ex)
            {
                // add your own exception handling here. There could be connection problems
                // or other problems with calling the database.
                throw ex;
            }
        }       

        private void UpdateComments(BlogPost post)
        {
            // using annoymous types, I can get the comments and the person
            var comments = from c in post.Comments
                           select new {c.Person.Name, c.CommentText };
            gridViewComment.DataSource = comments;
            gridViewComment.DataBind();
        }

        protected void buttonCreate_Click(object sender, EventArgs e)
        {
            try
            {
                // the short lived MyTravelPostEntities creates/destroys the connection
                // for the life of the using statement.
                using (MyTravelPostEntities entities = new MyTravelPostEntities())
                {
                    // deserializing and then reattaching allows the statemanager
                    // to track this post and the changes.
                    BlogPost post = (BlogPost)ViewState["BlogPost"];
                    entities.Attach(post);

                    // if we are updating, we may already have the comments,
                    // no need to go get these again.
                    if (post.Comments.Count() == 0)
                    {
                        // go get the comments with the person, then attach.
                        var comments = from c in entities.Comments.Include("Person")
                                       where c.BlogPost.BlogPostID == post.BlogPostID
                                       select c;
                        post.Comments.Attach(comments);
                    }   // if

                    // creating a new comment and add the first person
                    // the person does a query to fetch the people
                    // but you could also add the people to view state and attach
                    // then when setting you would just create the relationship
                    Comment newComment = new Comment();
                    newComment.CommentText = textComment.Text;
                    newComment.Person = entities.People.First();

                    post.Comments.Add(newComment);

                    try
                    {
                        entities.SaveChanges();
                    }
                    catch (OptimisticConcurrencyException opt)
                    {
                        // catching this exception allows you to 
                        // refresh entities with either store/client wins
                        // project the entities into this failed entities.
                        var failedEntities = from e1 in opt.StateEntries.ToList()
                                             select new { e1.Entity };

                        // Note: in future you should be able to just pass the opt.StateEntities in to refresh.
                        entities.Refresh(RefreshMode.ClientWins, failedEntities.ToList());
                        entities.SaveChanges();
                    }

                    textComment.Text = "";
                    UpdateComments(post);
                    ViewState["BlogPost"] = post;
                }   
            }   
            catch (Exception ex)
            {
                // add your own exception handling here. There could be connection problems
                // or other problems with calling the database.
                throw ex;
            }
        }

        protected void buttonUpdate_Click(object sender, EventArgs e)
        {
            try
            {
                // just for fun loop through all the comments and add a *
                // the short lived MyTravelPostEntities creates/destroys the connection
                // for the life of the using statement.
                using (MyTravelPostEntities entities = new MyTravelPostEntities())
                {
                    // deserializing and then reattaching allows the statemanager
                    // to track this post and the changes. 
                    BlogPost post = (BlogPost)ViewState["BlogPost"];
                    entities.Attach(post);

                    // if we are updating, we may already have the comments,
                    // no need to go get these again.
                    if (post.Comments.Count() == 0)
                    {
                        // go get the comments with the person, then attach.
                        var comments = from c in entities.Comments.Include("Person")
                                       where c.BlogPost.BlogPostID == post.BlogPostID
                                       select c;
                        post.Comments.Attach(comments);
                    }   // if

                    // loop through and add the *
                    foreach (Comment c in post.Comments)
                    {
                        c.CommentText += "*";
                    }

                    // once you have the reference, the properties are changed
                    // tracked so modifications are update during SaveChanges
                    try
                    {
                        entities.SaveChanges();
                    }
                    catch (OptimisticConcurrencyException opt)
                    {
                        // catching this exception allows you to 
                        // refresh entities with either store/client wins
                        // project the entities into this failed entities.
                        var failedEntities = from e2 in opt.StateEntries
                                             select new { e2.Entity };

                        // Note: in future you should be able to just pass the opt.StateEntities in to refresh.
                        entities.Refresh(RefreshMode.ClientWins, failedEntities.ToList());
                        entities.SaveChanges();
                    } 

                    UpdateComments(post);
                    ViewState["BlogPost"] = post;
                }
            }   
            catch (Exception ex)
            {
                // add your own exception handling here. There could be connection problems
                // or other problems with calling the database.
                throw ex;
            }
        }

        protected void buttonDelete_Click(object sender, EventArgs e)
        {
            try
            {
                // just for fun loop through all the comments and add a *
                // the short lived MyTravelPostEntities creates/destroys the connection
                // for the life of the using statement.
                using (MyTravelPostEntities entities = new MyTravelPostEntities())
                {
                    // deserializing and then reattaching allows the statemanager
                    // to track this post and the changes.
                    BlogPost post = (BlogPost)ViewState["BlogPost"];
                    entities.Attach(post);

                    // get the first comment and delete.
                    Comment toDelete = post.Comments.First();
                    entities.DeleteObject(toDelete);

                    // once you have the reference, the properties are changed
                    // tracked so modifications are update during SaveChanges
                    try
                    {
                        entities.SaveChanges();
                    }
                    catch (OptimisticConcurrencyException opt)
                    {
                        // catching this exception allows you to 
                        // refresh entities with either store/client wins
                        // project the entities into this failed entities.
                        var failedEntities = from e3 in opt.StateEntries
                                             select new { e3.Entity };

                        // Note: in future you should be able to just pass the opt.StateEntities in to refresh.
                        entities.Refresh(RefreshMode.ClientWins, failedEntities.ToList());
                        entities.SaveChanges();

                    } 

                    UpdateComments(post);
                    ViewState["BlogPost"] = post;
                }
            }   
            catch (Exception ex)
            {
                // add your own exception handling here. There could be connection problems
                // or other problems with calling the database.
                throw ex;
            }
        }
    }
}
